/**
 * 数据请求封装 
 * 
 * @author Gill Gong
 */

import qs from 'qs'
import config from '~/config'
import store from '~/common/store'

const SUCEESS_CODE = 0
const DEFAULT_CONTENT_TYPE = 'application/json'
const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded'

class AbstractModel {
  constructor ({ url, method, externHeaders = {}, isMockRequest }) {
    this.url = url
    this.method = method || 'Post'
    this.externHeaders = externHeaders
    this.isMockRequest = _.isBoolean(isMockRequest)? isMockRequest : config.isMockRequest
  }

  static FORM_CONTENT_TYPE = FORM_CONTENT_TYPE

  __exec ({ url, method, param }) {

    if(this.isMockRequest) {

      return Promise.resolve({

        json: function() {
          return { code: SUCEESS_CODE, result: "__mock_request__" }
        }
      })
    }

    return fetch(
      this.decoratorUrl(url, method, param), 
      {
        method,
        headers: this.getHeaders(),
        body: this.decoratorBody(method, param)
      }
    )
  }

  exec (param={}) {

    return new Promise((resolve, reject) => {

      this.__exec({
        param,
        url: this.url,
        method: this.method
      })
      .then(response=>response.json())
      .then((result)=>{
        
        if(this.isSuccess(result)) {
          resolve(result.data || result.result)
        }else{
          reject(result)
        }
      }).catch(reject)
    })
  }

  getHeaders() {
    
    return Object.assign(
      {
        'Content-Type': DEFAULT_CONTENT_TYPE,
        'accesstoken': store.getTokenSync()
      },
      this.externHeaders,
      this.getExternHeaders()
    )
  }

  isSuccess (result) {
    if (result) {
      return result.code === SUCEESS_CODE
    }
    
    return false
  }

  getExternHeaders () {
    return {}
  }

  decoratorUrl (url, method, param) {
    if (method.toLowerCase() === 'get' && !_.isEmpty(param)) {
      if (url.indexOf('?') > -1) {
        return url + '&' + qs.stringify(param)
      }

      return url + '?' + qs.stringify(param)
    }

    return url
  }

  decoratorBody (method, param) {
    let headers = this.getHeaders()

    if (method.toLowerCase() === 'get') {
      return ""
    }

    if(headers[ 'Content-Type' ] === FORM_CONTENT_TYPE) {
      return qs.stringify(param || {})
    }

    return JSON.stringify(param || {})
  }
}

export default AbstractModel
